package br.com.pentagrama.service.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import br.com.pentagrama.dto.InfoServico;
import br.com.pentagrama.dto.Parametros;
import br.com.pentagrama.exception.ParseConfException;
import br.com.pentagrama.service.IParametrosService;

public class ParametrosService implements IParametrosService {

	/*Privados*/
	private static ParametrosService instance;
	private Parametros parametros;
	private String urlParametro;
	private Map<Integer,List<String>> mapa;
	private Integer indice = null;
	
	public static ParametrosService getInstance(String urlParametros) {
		instance = new ParametrosService(urlParametros);
		return instance;
	}
	
	public static ParametrosService getInstance() {
		if(instance == null) {
			throw new RuntimeException("Classe Parametros não inicializada. Use getInstance(String urlParametros) para inicializar");
		}
		return instance;
	}
	
	private ParametrosService(String urlParametro) {
		if(urlParametro == null) {
			throw new IllegalArgumentException("O parâmtro urlParametro não deve ser nulo"); 
		}
		this.urlParametro = urlParametro;
		this.parametros = Parametros.getInstance();
		mapa = new HashMap<Integer, List<String>>();
	}
	
	public void carregarParametros() throws ParseConfException {
		InputStream in = null;
		
		try {
			URL url = new URL(urlParametro);
			HttpURLConnection connection = null;
		    connection = (HttpURLConnection) url.openConnection();
		    connection.setDoInput(true);  
	        connection.setDoOutput(false);  
		    connection.connect();
		    in = connection.getInputStream();
		    extrairLinhas(in);
		} catch(IOException e) {
			throw new ParseConfException("Erro fazer parse do arquivo de parâmetros", e);
		}
		
	    prepararParametros();
	    prepararServicos();
	}
	
	private void montarServico(InfoServico info, List<String> enderecos) throws ParseConfException {
		for (String conteudo : enderecos) {
			if(conteudo.trim().length() == 0) {
				continue;
			}
			String string = conteudo.substring(conteudo.indexOf(":") + 1).trim();
			if(conteudo.startsWith("TCP:")) {
				info.getTcpAcesso().addAll(info.getAcessosIndividuais(string));
			} else if(conteudo.startsWith("UDP:")) {
				info.getUdpAcesso().addAll(info.getAcessosIndividuais(string));				
			} else {
				throw new ParseConfException("Valor invalido no arquivo de parametros: " + string) ;
			}
		}
	}
	
	private void prepararServicos() throws ParseConfException {
		InfoServico videoDesktopMovel = parametros.getVideoDesktopMovel();
		InfoServico videoVidyo = parametros.getVideoSalasVydio();
		InfoServico videoOutros = parametros.getVideoSalasOutras();
		InfoServico gravacao = parametros.getGravacao();
		InfoServico webcasting = parametros.getWebCasting();
		
		videoDesktopMovel.setNome("Videoconferência Desktop/Móvel");
		videoVidyo.setNome("Videoconferência com Salas Físicas Vidyo");
		videoOutros.setNome("Videoconferência com Salas Físicas Outros Fabricantes");
		gravacao.setNome("Gravação");
		webcasting.setNome("Webcasting");
		
		montarServico(videoDesktopMovel, getLista(1));
		montarServico(videoVidyo, getLista(2));
		montarServico(videoOutros, getLista(3));
		montarServico(gravacao, getLista(4));
		montarServico(webcasting, getLista(5));
	}

	private void extrairLinhas(InputStream in) throws IOException {
		BufferedReader buffer=new BufferedReader(new InputStreamReader(in));
		String line = null;
		while ((line = buffer.readLine()) != null) {
			tratarParametros(line);
		}
	}
	
	
	public void prepararParametros() {
		for(String parametroCompleto : getLista(0)) {
			int indexOfIgual = parametroCompleto.indexOf("=");
			if(indexOfIgual > 0) {
				String chave = parametroCompleto.substring(0, indexOfIgual);
				String valor = parametroCompleto.substring(indexOfIgual+1);
				parametros.getChaveParametro().put(chave, valor);
			}
		}
	}
	
	public void tratarParametros(String linha) {
		if(linha.startsWith("#1")) {
			indice = 1;
		} else if(linha.startsWith("#2")) {
			indice = 2;
		} else if(linha.startsWith("#3")) {
			indice = 3;
		} else if(linha.startsWith("#4")) {
			indice = 4;
		} else if(linha.startsWith("#5")) {
			indice = 5;
		} else if(linha.startsWith("#Parametros")) {
			indice = 0;
		} else {
			getLista(indice).add(linha);
		}
	}
	
	public List<String> getLista(int indice) {
		if(mapa.get(indice) == null) {
			mapa.put(indice, new ArrayList<String>());
		}
		return mapa.get(indice);
	}

	/**
	 * Método "get" para o atributo mapa.
	 *
	 * @return Atributo mapa
	 */
	public Map<Integer, List<String>> getMapa() {
		return mapa;
	}
}
